[Grunt]grunt-contrib-jstでjsテンプレートを管理する。
今回はCUIツールのGruntのプラグインgrunt-contrib-jstを使ったjsテンプレートを管理する機会があたので一連の流れをご紹介します。
アジェンダ
- JavaScript Templates(JST)とは?
- Grunt-contrib-jstを使ってみる
JavaScript Templates(JST)とは?
テンプレート部分とデータ部分を関連づけて表示するイメージです。以下の記事がイメージしやすくとても参考になりました。
参考記事:JavaScriptテンプレートエンジンJsRender 基本のキ
それではJSTを用いて実際に表示してみたいと思います。今回はサンプルとして、Underscore.jsのテンプレートAPIを使って表示してみます。
使用したライブラリ
- jquery.js
- underscore.js
- backbone.js
- bootstrap.js
- bootstrap.css
テンプレート
scriptタグ内にhtmlタグがマークアップしています。これがjsテンプレートになります。
<%= %>はテンプレート内に変数を埋め込む表記です。
<script type="text/template" id="uiListItemTemplate"> <li class="item well"> <span class="name">Name : <%= name %></span><br /> <span class="age">Age : <%= age %></span> </li> </script>
モデルを作成
データを管理するしてくれるモデルを作成します。
var itemModel = Backbone.Model.extend({ defaults: { name : 'Test User', age : 20 } });
ビューを作成
今回は簡単な表示用のViewを作成します。8行目でunderscore.jsのメソッド_.template()でjsテンプレートとモデルが結合しています。
var listView = Backbone.View.extend({ el : '#uiLists', template : $('#uiListItemTemplate').html(), initialize: function(options) { this.render(); }, render: function() { var element = _.template( this.template , this.model.attributes ); this.$el.append(element); } });
表示する
モデル:itemModelをインスタンス化して、ビュー:listViewをインスタンス化する際に渡して表示します。
(function(){ var item = new itemModel; var lists = new listView({ model: item }); }());
ソースコード表示
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>JST Sample</title> <link rel="stylesheet" href="assets/css/lib/bootstrap.css"> <style type="text/css">#uiLists{margin-top: 20px; padding-right: 20px;}#uiLists li{list-style: none;}</style> </head> <body> <ul id="uiLists"></ul> <script type="text/template" id="uiListItemTemplate"> <li class="item well"> <span class="name">Name : <%= name %></span><br /> <span class="age">Age : <%= age %></span> </li> </script> <script type="text/javascript" src="assets/js/lib/underscore.js"></script> <script type="text/javascript" src="assets/js/lib/jquery.js"></script> <script type="text/javascript" src="assets/js/lib/bootstrap.js"></script> <script type="text/javascript" src="assets/js/lib/backbone.js"></script> <script type="text/javascript"> var itemModel = Backbone.Model.extend({ defaults: { name : 'Test User', age : 20 } }); var listView = Backbone.View.extend({ el : '#uiLists', template : $('#uiListItemTemplate').html(), initialize: function(options) { this.render(); }, render: function() { var element = _.template( this.template , this.model.attributes ); this.$el.append(element); } }); (function(){ var item = new itemModel; var lists = new listView({ model: item }); }()); </script> </body> </html>
表示するためでしたので結構はしょってしまっていますが、実際にJSテンプレートを使ってレンダリングしてみました。
今回は1つのページに1テンプレートでしたが、開発する際はJSテンプレート数が増えてきて管理も大変になってきます。
その問題を解決してくれるのがしてくれるのがビルドツールのGruntさんのプラグインgrunt-contrib-jstです。
Grunt-contrib-jstを使ってみる
grunt-contrib-jstは指定したフォルダ内のhtmlファイル(テンプレート)を、1つのUnderscore.jsのテンプレート用jsファイルに変換してくれます。
類似プラグインにHandlebarsテンプレート用のgrunt-contrib-handlebarsもあります。
package.json
それでは早速つかってみたいと思います。まず作業用フォルダを作成し、package.jsonを作成します。
今回使用するGruntプラグインを記載します。
- grunt-contrib-watch
- grunt-contrib-jst
{ "author": "Takashi Kiyota", "name": "grunt contrib jst Test", "version": "0.9.1", "devDependencies": { "grunt": "", "grunt-contrib-watch" : "", "grunt-contrib-jst" : "" } }
Nodeパッケージをインストール
プラグインのインストールしてみます、コンソール画面から作業ファイルまで移動し以下のコマンドを入力します。
cd xxx/xxx/xxxx/作業フォルダ npm install
Gruntfile.jsの作成
プラグインのインストールが出来たら、Gruntfile.jsを作成します。
gruntに指定したフォルダ内にjsテンプレート用のhtmlを作成します。監視フォルダと出力ファイルはGruntfile.js(26行目)で指定ができます。今回は以下の指定をしています。
- 監視フォルダ
- [assets/templates/]
- 出力ファイル
- [assets/js/jst/template.js]
module.exports = function (grunt) { 'use strict'; grunt.initConfig({ watch: { jst: { files: ['assets/templates/**/*.html'], tasks: ['jst:dev'] } }, jst: { options: { processName: function (filename) { return filename.match(/templates\/(.+)\.html$/)[1]; }, processContent: function (src) { return src.replace(/(^\s+|\s+$)/gm, ''); }, amd: true }, dev: { files: { 'assets/js/jst/template.js': ['assets/templates/**/*.html'] } } } }); grunt.registerTask('default', ['watch']); grunt.registerTask('build', ['jst']); };
jsテンプレート変換用htmlを作成
[assets/templates/]内にsample.htmlを作成します。テンプレート側で表示する際は、htmlのファイル名を指定して表示することになります。(今回はsampleになります。)
注意点として、scriptタグに囲まずにそのまま記述します。
<li class="item well"> <span class="name">Name : <%= name %></span><br /> <span class="age">Age : <%= age %></span> </li>
テンプレート出力
実際にテンプレートを出力してみます。コンソール画面に移動し作業フォルダのトップ階層に移動し、
以下コマンドを入力します。
grunt build
template.js
[assets/js/jst/]内にtemplate.jsがされていれば成功です。中身をみると先ほど作成したsample.html内の中身がテンプレート用に変換されています。
this["JST"] = this["JST"] || {}; this["JST"]["sample"] = function(obj) { obj || (obj = {}); var __t, __p = '', __e = _.escape; with (obj) { __p += '<li class="item well">\n<span class="name">Name : ' + ((__t = ( name )) == null ? '' : __t) + '</span><br />\n<span class="age">Age : ' + ((__t = ( age )) == null ? '' : __t) + '</span>\n</li>'; } return __p };
変換されたテンプレートファイルで表示する
1.template.jsを読み込む
Grunt-contrib-jstで変換されたテンプレートを読み込みます。
<script type="text/javascript" src="assets/js/jst/template.js"></script>
2.ビュー(View)の編集
3行目の箇所でcontrib-jst作成されたオブジェクトJST[]にテンプレート用htmlの名前を指定します。
今回はsample.htmlだったので、JST['sample']になります。
8行目のthis.template()の引数にモデルが保持しているデータを渡しています。
var listView = Backbone.View.extend({ el : '#uiLists', template : JST['sample'], initialize: function(options) { this.render(); }, render: function() { var element = this.template(this.model.attributes); this.$el.append(element); } });
ソースコード
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>JST Sample</title> <link rel="stylesheet" href="assets/css/lib/bootstrap.css"> <style type="text/css">#uiLists{margin-top: 20px; padding-right: 20px;}#uiLists li{list-style: none;}</style> </head> <body> <ul id="uiLists"></ul> <script type="text/javascript" src="assets/js/lib/underscore.js"></script> <script type="text/javascript" src="assets/js/lib/jquery.js"></script> <script type="text/javascript" src="assets/js/lib/bootstrap.js"></script> <script type="text/javascript" src="assets/js/lib/backbone.js"></script> <script type="text/javascript" src="assets/js/jst/template.js"></script> <script type="text/javascript"> var itemModel = Backbone.Model.extend({ defaults: { name : 'Test User', age : 20 } }); var listView = Backbone.View.extend({ el : '#uiLists', template : JST['sample'], initialize: function(options) { this.render(); }, render: function() { var element = this.template(this.model.attributes); this.$el.append(element); } }); (function(){ var item = new itemModel; var lists = new listView({ model: item }); }()); </script> </body> </html>
まとめ
grunt-contrib-jstでJSテンプレートを外部ファイルtemplate.jsとして出力まで試してみました。自分的には以下の利点があるかと思いました。
- 1.ソースコード内にテンプレートを記述しなくて良い。
- grunt-contrib-jstで変換されたjsファイルを読み込むだけで良い。
- 2.テンプレートの管理が楽チン
- 監視フォルダ[assets/templates/]の各htmlがテンプレートとなるため、該当するテンプレートの管理・編集が容易になります。